/*
 * INSANE - Interactive Structural Analysis Environment
 *
 * Copyright (C) 2003-2006
 * Universidade Federal de Minas Gerais
 * Escola de Engenharia
 * Departamento de Engenharia de Estruturas
 *
 * Author's email :     insane@dees.ufmg.br
 * Author's Website :   http://www.dees.ufmg.br/insane
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
 
package br.ufmg.dees.insane.draw;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.text.DecimalFormat;
import java.util.ListIterator;
import java.util.Vector;

/**
 * This class represents a draw of a scale given a
 * baseline, a maximum and
 * minimum values.
 *
 * The maximum and minimum values are used to compose
 * the color pallete that goes from red to blue passing by
 * white.
 *
 * @author Fonseca, Flavio & Pitangueira, Roque
 * @since April 2004
 */
public class ScaleDraw extends Draw {
    
    private double max = 0;
    private double min = 0;
    
//*****************************************************************************
	
    /**
     * Construct a new empty ScaleDraw.
     */
    public ScaleDraw() {
		this(new Point());
    }
    
//*****************************************************************************
	
    /**
     * Constructs a new ScaleDraw with
     * a given baseline(LineDraw)
     *
     * @param    location    The desired baseline
     */
    public ScaleDraw(Point location) {
        this(100, 0, location);
    }
	
//*****************************************************************************
	
    /**
     * Constructs a new DiagramDraw with a baseline and an
     * array of double values to represent. The given max and min
     * are used to compose the color pallette.
     *
     * @param    max   The maximum value to compose the color pallete
     * @param    min    The minimum value to compose the color pallete
     * @param    location   The baseline of the diagram.
     */
    public ScaleDraw(double max, double min, Point location) {
        this(max, min, location, "");
    }
    
//*****************************************************************************
	
    /**
     * Constructs a new DiagramDraw with a baseline and an
     * array of double values to represent. The given max and min
     * are used to compose the color pallette.
     *
     * @param    max   The maximum value to compose the color pallete
     * @param    min    The minimum value to compose the color pallete
     * @param    location   The baseline of the diagram.
     */
    public ScaleDraw(double max, double min, Point location, String label) {
        this.max = max;
        this.min = min;
        this.setLocation(location);
		this.setLabel(label);
		this.setSize(new Dimension(200, 10));
    }
    
//*****************************************************************************
	
    /**
     * Sets the maximum param of the diagram to
     * use in color scalling
     *
     * @param   max  The max param for color scalling
     */
    public void setMax(double max) {
        this.max = max;
    }
    
//*****************************************************************************
	
    /**
     * Gets the maximum param of the diagram used in
     * color scalling
     *
     * @return    The maximum param for color scaling
     */
    public double getMax() {
        return max;
    }
    
//*****************************************************************************
	
    /**
     * Sets the minimum param of the diagram to
     * use in color scalling
     *
     * @param   min  The minimum param for color scalling
     */
    public void setMin(double min) {
        this.min = min;
    }
    
//*****************************************************************************
	
    /**
     * Gets the minimum param of the diagram used in
     * color scalling
     *
     * @return    The minimum param for color scaling
     */
    public double getMin() {
        return min;
    }
    
//*****************************************************************************
	
    /**
     * Returns a vector of shapes that compose the
     * diagram drawing.
     *
     * The shapes are lines representing the values of
     * the vector received by the constructor scaled by
     * the scale of this draw in an angle of ninety degrees
     * from baseline, and a GeneralPath that rounds the
     * diagram.
     *
     * @return    A Vector of shapes tha compose the diagram.
     */
    public Vector<Object> getShapes() {
        Vector<Object> shapes = new Vector<Object>();
        
        Point2D loc = new Point2D.Double();
        Point2D oldLoc = new Point2D.Double();
        Point2D loc2 = new Point2D.Double();
        Point2D oldLoc2 = new Point2D.Double();
        double width = this.getSize().width;
        double ang = Math.PI/2;
        double inc = width/100;
        double val = this.getSize().height;
        GeneralPath shape = new GeneralPath(new Line2D.Double(this.getLocation(), this.getLocation()));
        GeneralPath trap = new GeneralPath(new Line2D.Double(this.getLocation(), this.getLocation()));
        
        for (int i = 0; i < 100; i++) {
            
            if (i < 1) {
                loc = this.getLocation();
                oldLoc = loc;
                loc2 = new Point2D.Double(loc.getX() + val*Math.sin(ang), loc.getY() - val*Math.cos(ang));
                oldLoc2 = loc2;
                
                shape.lineTo((float)loc2.getX(), (float)loc2.getY());
            } else if (i < 99) {
                loc = new Point2D.Double(this.getLocation().x + (i * inc)*Math.cos(ang),
                this.getLocation().y + (i * inc)*Math.sin(ang));
                loc2 = new Point2D.Double(loc.getX() + val*Math.sin(ang), loc.getY() - val*Math.cos(ang));
                
                trap = new GeneralPath(new Line2D.Double(oldLoc, oldLoc));
                trap.lineTo((float)oldLoc2.getX(), (float)oldLoc2.getY());
                trap.lineTo((float)loc2.getX(), (float)loc2.getY());
                trap.lineTo((float)loc.getX(), (float)loc.getY());
                trap.closePath();
                shapes.add(trap);
                oldLoc = loc;
                oldLoc2 = loc2;
                
                shape.lineTo((float)loc2.getX(), (float)loc2.getY());
            } 
            if (i == 99) {
                loc = new Point2D.Double(this.getLocation().x + (i * inc)*Math.cos(ang),
                this.getLocation().y + (i * inc)*Math.sin(ang));
                loc2 = new Point2D.Double(loc.getX() + val*Math.sin(ang), loc.getY() - val*Math.cos(ang));
                
                shape.lineTo((float)loc2.getX(), (float)loc2.getY());
                
                trap = new GeneralPath(new Line2D.Double(oldLoc, oldLoc));
                trap.lineTo((float)oldLoc2.getX(), (float)oldLoc2.getY());
                trap.lineTo((float)loc2.getX(), (float)loc2.getY());
                trap.lineTo((float)loc.getX(), (float)loc.getY());
                trap.closePath();
                shapes.add(trap);
                
                shape.lineTo((float)loc.getX(), (float)loc.getY());
                shape.closePath();
            }
        }
        shapes.add(shape);
        
        return shapes;
        
    }
    
//*****************************************************************************
	
    /**
     * Returns a rectangle that is the bounding box of
     * the diagram.
     *
     * Its is base in the maximum and minimum values
     * of the received vector of values NOT the maximum and
     * minimum variables.
     *
     * @return    The bounding box rectangle
     */
    public Rectangle getBounds() {
        
        //Choosing the location point of the bounds;
        double scale = this.getScale();
        Point loc = this.getLocation();
        int x = loc.x;
        int y = loc.y;
        
        double width = 3 * scale * 100;
        double height = 10 * scale;
        
        int W = (int)(width);
        int H = (int)(height*scale);
        
        return new Rectangle(x - 1, y + 1, W + 2, H + 2);
    }
    
//*****************************************************************************
	
    /**
     * Draws the shapes given by the method <pre>getShapes()</pre>
     * in a given Graphics2D.
     *
     * The colors of the patern are from red(maximum value) to
     * blue(minimum value) passing by white(medium).
     *
     * @see   java.awt.Graphics2D
     */
    public void draw(Graphics2D g2) {
        
        Vector shapes = getShapes();
        Shape shp;
        
        Color currentColor = g2.getColor();
        
        //==== Filling the scale
        double c = 0;
	double val = 0;
        
	//The Red, Green and Blue values to the color
        int r = 0;
        int b = 0;
        int g = 0;
        
        int i = 1;
        int size = shapes.size();
        ListIterator shps = shapes.listIterator();
        while(shps.hasNext()){
            shp = (Shape)shps.next();
            if (i<size) {
                val = (i*(max-min))/100 + min;
                c = ((val-min)/(max-min))*510;
                if (c < 255) {
                    g = (int)c;
                    b = g;
                    r =255;
                } else {
                    g = (int)(510 - c);
                    r = g;
                    b = 255;
                }
                g2.setColor(new Color(r, g, b));
            	g2.fill(shp);
            }
            i++;
        }
        //==== End of filling
        
        //==== Drawing the contour
        shp = (Shape)shapes.get(shapes.size() - 1);
        g2.setColor(currentColor);
        g2.draw(shp);
        //==== End of drawing the contour
		
		//==== Drawing the labels
		DecimalFormat form = new DecimalFormat("##0.###E0");
		int width = this.getSize().width;
		int height = this.getSize().height;
		g2.drawString(this.getLabel(), this.getLocation().x, this.getLocation().y - 15);
		g2.draw(new Line2D.Double(this.getLocation().x + height, this.getLocation().y, 
		this.getLocation().x + height + 5, this.getLocation().y));
		g2.drawString("" + form.format(max), this.getLocation().x + height + 10, this.getLocation().y);
		g2.draw(new Line2D.Double(this.getLocation().x + height, this.getLocation().y + width/4, 
		this.getLocation().x + height + 5, this.getLocation().y + width/4));
		g2.drawString("" + form.format(0.75*max + 0.25*min), this.getLocation().x + height + 10, this.getLocation().y + width/4);
		g2.draw(new Line2D.Double(this.getLocation().x + height, this.getLocation().y + width/2, 
		this.getLocation().x + height + 5, this.getLocation().y + width/2));
		g2.drawString("" + form.format(0.5*max + 0.5*min), this.getLocation().x + height + 10, this.getLocation().y + width/2);
		g2.draw(new Line2D.Double(this.getLocation().x + height, this.getLocation().y + 3*width/4, 
		this.getLocation().x + height + 5, this.getLocation().y + 3*width/4));
		g2.drawString("" + form.format(0.25*max + 0.75*min), this.getLocation().x + height + 10, this.getLocation().y + 3*width/4);
		g2.draw(new Line2D.Double(this.getLocation().x + height, this.getLocation().y + width - 2, 
		this.getLocation().x + height + 5, this.getLocation().y + width - 2));
		g2.drawString("" + form.format(min), this.getLocation().x + height + 10, this.getLocation().y + width);
        
        if (isSelected()) {
            g2.setColor(new Color(255, 0, 0));
            Shape s = this.getRotatedBounds();
            g2.draw(s);
        }
        
        g2.setColor(currentColor);
    }
    
//*****************************************************************************
}
